package com.chandra.pos.order.dao.entity;

import com.chandra.pos.customer.dao.entity.Customer;
import com.chandra.pos.employee.dao.entity.Employee;
import com.chandra.pos.model.PosEntity;
import com.chandra.pos.order.model.OrderStatus;
import com.chandra.pos.order.model.OrderType;
import com.chandra.pos.order.model.ShippingStatus;
import com.chandra.pos.product.dao.entity.Product;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;

import javax.persistence.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Customer: T4671
 * Date: 10/5/13
 * Time: 10:25 AM
 * To change this template use File | Settings | File Templates.
 */
@Entity
@Table(name="ORDERS")
public class Order extends PosEntity {

    public static int AMOUNT_PRECISION = 2;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "orderId", cascade = CascadeType.ALL, orphanRemoval = true)
    protected List<OrderItem> items =new ArrayList<OrderItem>();

    @Column(name = "SHIPPING_AMOUNT")
    private BigDecimal shippingAmount = BigDecimal.ZERO;

    @Column(name = "TOTAL_AMOUNT")
    private BigDecimal totalAmount = BigDecimal.ZERO;

    @Column(name = "DUE_AMOUNT")
    private BigDecimal dueAmount = BigDecimal.ZERO;

    @Column(name = "DUE_DATE")
    private Long dueDate;


    /*
     Tax amount to be calculated in total amount
    */
    @Column(name = "TAX_AMOUNT")
    private BigDecimal taxAmount = BigDecimal.ZERO;
    /*
      Miscellaneous charges
     */
    @Column(name = "OTHER_AMOUNT")
    private BigDecimal otherCharge = BigDecimal.ZERO;

    @Column(name = "DISCOUNT")
    private BigDecimal discount = BigDecimal.ZERO;

    @Column(name = "ORDER_DATE")
    private long orderDate;

    @Column(name = "SHIPPING_DATE")
    private long shippingDate;

    @Column(name = "NOTE")
    private String note;

    @Enumerated(EnumType.ORDINAL)
    @Column(name = "STATUS_ID")
    private OrderStatus status;

    @Enumerated(EnumType.ORDINAL)
    @Column(name = "SHIPPING_STATUS_ID")
    private ShippingStatus shippingStatus;

    @OneToOne
    @JoinColumn(name = "CUSTOMER_ID", unique = false, nullable = true, updatable = false, insertable = false)
    @NotFound(action = NotFoundAction.IGNORE)
    private Customer customer;

    @Column(name = "CUSTOMER_ID" , nullable = true)
    private Long customerId;


    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "USER_ID", unique = false, nullable = true, updatable = true, insertable = true)
    @NotFound(action = NotFoundAction.IGNORE)
    private Employee employee;


    @Enumerated(EnumType.ORDINAL)
    @Column(name = "ORDER_TYPE_ID")
    private OrderType orderType;

    public ShippingStatus getShippingStatus() {
        return shippingStatus;
    }

    public void setShippingStatus(ShippingStatus shippingStatus) {
        this.shippingStatus = shippingStatus;
    }

    public OrderStatus getStatus() {
        return status;
    }

    public void setStatus(OrderStatus status) {
        this.status = status;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public long getShippingDate() {
        return shippingDate;
    }

    public void setShippingDate(long shippingDate) {
        this.shippingDate = shippingDate;
    }

    public long getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(long orderDate) {
        this.orderDate = orderDate;
    }

    public BigDecimal getDiscount() {
        return discount;
    }

    public void setDiscount(BigDecimal discount) {
        this.discount = discount;
    }

    public BigDecimal getTaxAmount() {
        return taxAmount;
    }

    public void setTaxAmount(BigDecimal taxAmount) {
        this.taxAmount = taxAmount;
    }

    public BigDecimal getOtherCharge() {
        return otherCharge;
    }

    public void setOtherCharge(BigDecimal otherCharge) {
        this.otherCharge = otherCharge;
    }

    public Long getDueDate() {
        return dueDate;
    }

    public void setDueDate(Long dueDate) {
        this.dueDate = dueDate;
    }

    public BigDecimal getDueAmount() {
        return dueAmount;
    }

    public void setDueAmount(BigDecimal dueAmount) {
        this.dueAmount = dueAmount;
    }

    public BigDecimal getTotalAmount() {
        BigDecimal total = getSubTotalAmount();
        if (discount != null)
            total = total.subtract(discount);

        if (otherCharge != null)
            total = total.add(otherCharge);

        if (taxAmount != null)
            total = total.add(taxAmount);

        if (shippingAmount != null)
            total = total.add(shippingAmount);

        totalAmount = total.setScale(AMOUNT_PRECISION, RoundingMode.HALF_UP);


        return totalAmount;

    }

    public void setTotalAmount(BigDecimal totalAmount) {
        this.totalAmount = totalAmount;
    }

    public BigDecimal getShippingAmount() {
        return shippingAmount;
    }

    public void setShippingAmount(BigDecimal shippingAmount) {
        this.shippingAmount = shippingAmount;
    }

    public List<OrderItem> getItems() {
        return items;
    }

    public void setItems(List<OrderItem> items) {
        this.items = items;
    }

    @Transient
    public BigDecimal getSubTotalAmount() {


        BigDecimal subTotal = new BigDecimal(0);

        if (items != null)
            for (OrderItem item : items) {

                subTotal = subTotal.add(item.getTotalAmount());

            }

        subTotal = subTotal.setScale(AMOUNT_PRECISION, RoundingMode.HALF_UP);

        return subTotal;
    }
    @Transient
    public boolean addOrderItem(Product product, BigDecimal quantity, BigDecimal salePrice, BigDecimal costPrice) {

        boolean found = false;

        for (OrderItem itemEntity : items) {

            if (itemEntity.getProduct().getId().equals( product.getId())) {   //if item already exist in order update order quantity
                itemEntity.setQuantity(itemEntity.getQuantity().add(quantity));
                found = true;
                break;
            }

        }

        if (!found) {
            OrderItem item = new OrderItem();
            item.setQuantity(quantity);
//            if (this.getOrderType().getId() == OrderType.SALE.getId())
//                item.setSalePrice(salePrice);
//            else
                item.setSalePrice(salePrice);
            item.setProduct(product);
            item.setDiscount(new BigDecimal(0));
            //item.setOrder(this);
            items.add(item);
        }


        return true;  //To change body of created methods use File | Settings | File Templates.
    }

    @Transient
    public boolean editOrderItem(Product product, BigDecimal quantity, BigDecimal salePrice, BigDecimal costPrice, BigDecimal discount) {

        boolean productFound = false;

        for (OrderItem itemEntity : items) {

            if (itemEntity.getProduct().getId() == product.getId()) {
                itemEntity.setQuantity(quantity);
//                if (this.getOrderType().getId() == OrderType.PURCHASE.getId())
//                    itemEntity.setSalePrice(costPrice);
//                else if (this.getOrderType().getId() == OrderType.SALE.getId())
                    itemEntity.setSalePrice(salePrice);


                itemEntity.setDiscount(discount);
                productFound = true;
                break;
            }
        }
//
        return true;  //To change body of created methods use File | Settings | File Templates.
    }

    @Transient
    public boolean removeOrderItem(Product product) {

        boolean found = false;


        for (OrderItem itemEntity : items) {

            if (itemEntity.getProduct().getId() == product.getId()) {
                items.remove(itemEntity);
                found = true;
                break;
            }

        }

        if (!found) {
            return false;
        }
        if (this.getItems().isEmpty()) {  //if no items in cart

            this.setDiscount(new BigDecimal(0));   //clear the discount as well as shipping charge
            this.setShippingAmount(new BigDecimal(0));

        }


        return true;  //To change body of created methods use File | Settings | File Templates.
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public Long getCustomerId() {
        return customerId;
    }

    public void setCustomerId(Long customerId) {
        this.customerId = customerId;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public OrderType getOrderType() {
        return orderType;
    }

    public void setOrderType(OrderType orderType) {
        this.orderType = orderType;
    }
}
